﻿// --------------------------------------------------------------------------------------------------------------------- 
// <copyright file="EnvironmentManager.cs" company="Microsoft.Blueprints.Contrib Team">
//   (C) 2009 Microsoft.Blueprints.Contrib Team
// </copyright>
// <summary>
//   An abstraction over various context and Visual Studio integration components.
// </summary>
// ---------------------------------------------------------------------------------------------------------------------

namespace Microsoft.Blueprints.Contrib.Environment
{
    #region Using Directives

    using System;
    using System.Collections.Generic;
    using System.IO;

    using EnvDTE;

    using Microsoft.SoftwareFactories.Blueprints;

    #endregion

    /// <summary>
    /// An abstraction over various context and Visual Studio integration components.
    /// </summary>
    public class EnvironmentManager
    {
        /// <summary>
        /// The Blueprint Manager Context
        /// </summary>
        private readonly BPMContextBase context;

        /// <summary>
        /// Currently selected project.
        /// </summary>
        private Project selectedProject;

        /// <summary>
        /// Initializes a new instance of the <see cref="EnvironmentManager"/> class.
        /// </summary>
        /// <param name="context">
        /// The context.
        /// </param>
        public EnvironmentManager(BPMContextBase context)
        {
            this.context = context;
        }

        /// <summary>
        /// Gets the full path to the select project's directory
        /// </summary>
        /// <remarks>
        /// Throws an InvalidCastException if a Project was not selected
        /// </remarks>
        public string SelectedProjectDirectory
        {
            get
            {
                return Path.GetDirectoryName(this.SelectedProject.FileName);
            }
        }

        /// <summary>
        /// Gets the filename of the selected project
        /// </summary>
        /// <remarks>
        /// Throws an InvalidCastException if a Project was not selected
        /// </remarks>
        public string SelectedProjectFilename
        {
            get
            {
                return this.SelectedProject.FileName;
            }
        }

        /// <summary>
        /// Gets the type of item that was clicked on to initiate the command
        /// </summary>
        public SolutionExplorerNode SolutionExplorerNode
        {
            get
            {
                if (this.context.Target is Project)
                {
                    return SolutionExplorerNode.Project;
                }

                if (this.context.Target is Solution)
                {
                    return SolutionExplorerNode.Solution;
                }

                return SolutionExplorerNode.Other;
            }
        }

        /// <summary>
        /// Gets SelectedProject.
        /// </summary>
        /// <exception cref="InvalidCastException">
        /// </exception>
        /// <value>
        /// The selected project.
        /// </value>
        private Project SelectedProject
        {
            get
            {
                Project currentlySelectedProject = this.context.Target as Project;

                if (currentlySelectedProject == null)
                {
                    if (this.selectedProject != null)
                    {
                        currentlySelectedProject = this.selectedProject;
                    }
                    else
                    {
                        throw new InvalidCastException("The selected item was not a Visual Studio Project.");
                    }
                }

                return currentlySelectedProject;
            }
        }

        /// <summary>
        /// Adds a list of files to the selected project
        /// </summary>
        /// <param name="files">
        /// A list of paths to files to add.
        /// </param>
        /// <remarks>
        /// Throws an InvalidCastException if a Project was not selected
        /// </remarks>
        public void AddProjectItemsToSelectedProject(List<string> files)
        {
            foreach (string file in files)
            {
                this.AddProjectItemToSelectedProject(file);
            }
        }

        /// <summary>
        /// Adds a file to the selected project
        /// </summary>
        /// <param name="filename">
        /// The full path to the file to add
        /// </param>
        public void AddProjectItemToSelectedProject(string filename)
        {
            this.SelectedProject.ProjectItems.AddFromFile(filename);
        }

        /// <summary>
        /// Copies a list of files to the selected project
        /// </summary>
        /// <param name="files">
        /// A list of paths to files to add.
        /// </param>
        public void CopyProjectItemsToSelectedProject(List<string> files)
        {
            foreach (string file in files)
            {
                this.CopyProjectItemToSelectedProject(file);
            }
        }

        /// <summary>
        /// Copies a file to the selected project
        /// </summary>
        /// <param name="filename">
        /// The full path to the file to copy
        /// </param>
        public void CopyProjectItemToSelectedProject(string filename)
        {
            this.SelectedProject.ProjectItems.AddFromFileCopy(filename);
        }

        /// <summary>
        /// Adds a project file to the current solution.
        /// </summary>
        /// <param name="projectFilename">
        /// Project to add to the solution.
        /// </param>
        public void AddProjectToSolution(string projectFilename)
        {
            this.context.DTE.Solution.AddFromFile(projectFilename, false);
        }

        /// <summary>
        /// Sets the selected project
        /// </summary>
        /// <param name="project">
        /// New selected project
        /// </param>
        public void SelectProject(Project project)
        {
            this.selectedProject = project;
        }
    }
}